#pragma once
#include<iostream>
using namespace std;
#include"reverse.h"
namespace ysl
{
	template<class T>
	struct  ListNode
	{
		ListNode<T>* _next;
		ListNode<T>* _prev;
		T _Data;

		ListNode(const T& x = T())
			:_next(nullptr)
			,_prev(nullptr)
			,_Data(x)
		{}
		
	};

	template<class T,class Ref,class Ptr>
	struct _list_iterator
	{
		typedef ListNode<T> Node;
		typedef _list_iterator<T,Ref,Ptr> self;
		Node* _node;
		_list_iterator(const self& l)
		{
			_node = l._node;
		}
		_list_iterator(Node* x)
			:_node(x)
		{}
		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}
		self operator++(int)
		{
			self tmp(*this);
			_node = _node->_next;
			return tmp;
		}
		self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}
		self operator--(int)
		{
			self tmp(*this);
			_node = _node->_prev;
			return tmp;
		}
		Ptr  operator->()
		{
			return &_node->_Data;
		}
		Ref operator*()
		{
			return _node->_Data;
		}
		bool operator!=(const self& s)
		{
			return _node != s._node;
		}
		bool operator==(const self& s)
		{
			return _node == s._node;
		}
	};
	//template<class T>
	//struct _list_const_iterator
	//{
	//	typedef ListNode<T> Node;
	//	typedef _list_const_iterator<T> self;
	//	Node* _node;
	//	_list_const_iterator(const self& l)
	//	{
	//		_node = l._node;
	//	}
	//	_list_const_iterator(Node* x)
	//		:_node(x)
	//	{}
	//	self& operator++()
	//	{
	//		_node = _node->_next;
	//		return *this;
	//	}
	//	self operator++(int)
	//	{
	//		self tmp(*this);
	//		_node = _node->_next;
	//		return tmp;
	//	}
	//	self& operator--()
	//	{
	//		_node = _node->_prev;
	//		return *this;
	//	}
	//	self operator--(int)
	//	{
	//		self tmp(*this);
	//		_node = _node->_prev;
	//		return tmp;
	//	}
	//	const T& operator*()
	//	{
	//		return _node->_Data;
	//	}
	//	bool operator!=(const self& s)
	//	{
	//		return _node != s._node;
	//	}
	//	bool operator==(const self& s)
	//	{
	//		return _node == s._node;
	//	}
	//};
	template<class T>
	class list
	{
		typedef ListNode<T> Node;
	public:
		typedef _list_iterator<T,T&,T*> iterator;
		typedef _list_iterator<T,const T&,const T*> const_iterator;

		typedef Reverse_iterator<iterator, T&, T*> reverse_iterator;
		typedef Reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;


		void empty()
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
		}
		void swap(list<T>& l)
		{
			std::swap(_head,l._head);
		}
		list<T>& operator=(list<T>& l)
		{
			swap(l);
			return *this;
		}
		list()
		{
			empty();
		}
		list(int n, const T& value = T())
		{
			empty();
			int i = 0;
			while (i < n)
			{
				push_back(value);
				++i;
			}
		}
		list(list<T>& a)
		{
			empty();
			for (auto e : a)
			{
				push_back(e);
			}
		}
		template <class Iterator>
		list(Iterator first, Iterator last)
		{
			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}
		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}
		void clear()
		{
			iterator lt = begin();
			while (lt != end())
			{
				lt = erase(lt);
			}
		}
		void push_back(const T& x)
		{
			//Node* newnode = new Node(x);
			//Node* tail = _head->_prev;

			//tail->_next = newnode;
			//newnode->_prev = tail;
			//newnode->_next = _head;
			//_head->_prev = newnode;
			insert(end(), x);
		}
		void push_front(const T& x)
		{
			insert(begin(), x);
		}
		void pop_back()
		{
			erase(--end());
		}
		void pop_front() { erase(begin()); }
		
		iterator insert(iterator pos, const T& x)
		{
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* newnode = new Node(x);

			newnode->_next = cur;
			cur->_prev = newnode;
			newnode->_prev = prev;
			prev->_next = newnode;
			return newnode;
		}
		iterator erase(iterator pos)
		{
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;
			prev->_next = next;
			delete cur;
			return next;
		}
		reverse_iterator rbegin()
		{
			return reverse_iterator(end());
		}
		reverse_iterator rend()
		{
			return reverse_iterator(begin());
		}
		iterator end()
		{
			return _head;
		}
		iterator begin()
		{
			return _head->_next;
		}
		const_iterator cend()const
		{
			return const_iterator(_head);
		}
		const_iterator cbegin()const
		{
			return const_iterator(_head->_next);
		}

	private:
		Node* _head;
	};
	void text1()
	{
		list<int> a;
		a.push_back(2);
		a.push_back(5);
		a.push_back(5);
		a.push_back(5);
		a.insert(a.begin(), 4);
		a.push_front(8);
		list<int>::iterator it = a.begin();
		while (it!=a.end())
		{
			cout << *it << " ";
			it++;
		}
	}
	void text2()
	{
		list<int> a;
		a.push_back(2);
		a.push_back(5);
		
		
		//a.erase(a.begin());
		
		a.pop_back();
		list<int>::iterator it = a.begin();
		while (it != a.end())
		{
			cout << *it << " ";
			it++;
		}
	}
	void text3()
	{
		list<int> a;
		a.push_back(2);
		a.push_back(5);
		a.push_back(5);
		a.push_back(5);

		//a.erase(a.begin());

		list<int>::iterator it = a.begin();
		while (it != a.end())
		{
			cout << *it << " ";
			it++;
		}
		for (auto e : a)
		{
			cout << e << " ";
		}
	}
	void text4(const list<int>& a)
	{
		list<int>::const_iterator lt = a.cbegin();
		while (lt != a.cend())
		{
			//*lt+=10;
			lt++;
		}
	}
	void text5()
	{
		list<int> a(5, 1);
		list<int>::iterator lt = a.begin();
		for (auto e : a)
		{
			cout << e << " ";
		}
	}
	void text6()
	{
		list<int> a;
		list<int> b;
		a.push_back(2);
		a.push_back(5);
		a.push_back(5);
		a.push_back(5);
		b.push_back(3);
		a = b;
		list<int>::iterator lt = a.begin();
		for (auto e : a)
		{
			cout << e << " ";
		}
	}


	void text7()
	{
		class a
		{
		public:
			int _c;
			int _b;
			a()
				:_c(0)
				,_b(1)
			{}

		};
		list<a> b;
		b.push_back(a());
		b.push_back(a());
		list<a>::iterator lt = b.begin();
		while (lt!=b.end())
		{
			/*cout << lt->_b << " "<< lt->_c;*/
			cout << lt.operator->()->_b << " ";
			lt++;
		}		
			
	}
		
	void text8()
	{
		list<int> a;
		a.push_back(2);
		a.push_back(5);
		a.push_back(5);
		a.push_back(5);

		//a.erase(a.begin());

		list<int>::reverse_iterator it = a.rbegin();
		while (it != a.rend())
		{
			cout << *it << " ";
			it++;
		}
	}

}